using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using DL_Content_Builder;
using System.Diagnostics;
using System.Net;
using System.IO;
using System.Xml;
using EsuApiLib;


namespace MonsterMashGame2
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class ShowDocumentumModel : Microsoft.Xna.Framework.GameComponent
    {

        // Cache information about the model size and position.
        Matrix[] boneTransforms;
        Vector3 modelCenter = new Vector3(10, 10, 10);
        float modelRadius = 2;
        Model starship;
        Model cylinder;
        protected Boolean screenReady = false;

        // Timer controls the rotation speed.
        Stopwatch timer;

        public ShowDocumentumModel(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            if (screenReady)
            {
                return;
            }

            timer = new Stopwatch();
            timer.Start();

            MonsterMashStreamingServiceClient client = new MonsterMashStreamingServiceClient();
            client.ClientCredentials.Windows.ClientCredential.Domain = CredentialCache.DefaultNetworkCredentials.Domain;
            client.ClientCredentials.Windows.ClientCredential.Password = CredentialCache.DefaultNetworkCredentials.Password;
            client.ClientCredentials.Windows.ClientCredential.UserName = CredentialCache.DefaultNetworkCredentials.UserName;
            client.ClientCredentials.Windows.AllowNtlm = true;

            String[] objectIDs = client.GetListOfContentObjects("SELECT * FROM dl_model WHERE r_object_id = '" + CurrentState.DocumentumObjectID + "'");

            if (objectIDs.Count() < 1)
            {
                return;
            }
            String objID = objectIDs[0];
            Byte[] modelBytes = client.GetDocumentumContent(objID);


            String modelFilename = Game.Content.RootDirectory + "\\myship.fbx";
            FileStream modelContent = new FileStream(modelFilename, FileMode.Create);
            BinaryWriter modelWriter = new BinaryWriter(modelContent);
            modelWriter.Write(modelBytes);
            modelWriter.Flush();
            modelWriter.Close();

            Byte[] textureBytes = client.GetDocumentumContent(objectIDs[1]);
            String textureFilename = Game.Content.RootDirectory + "\\wedge_p2_diff_v1.tga";
            FileStream textureContent = new FileStream(textureFilename, FileMode.Create);
            BinaryWriter textureWriter = new BinaryWriter(textureContent);
            textureWriter.Write(textureBytes);
            textureWriter.Flush();
            textureWriter.Close();

            ContentBuilder myBuilder = new ContentBuilder();
            myBuilder.Add(modelFilename, "myship.fbx", null, "ModelProcessor");

            String buildError = myBuilder.Build();

            starship = Game.Content.Load<Model>(myBuilder.OutputDirectory + @"\myship.fbx");

            MeasureModel();


            base.Initialize();

            screenReady = true;

        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public void Draw(GameTime gameTime)
        {
            Game.GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here
            // Compute camera matrices.
            float rotation = (float)timer.Elapsed.TotalSeconds;

            Vector3 eyePosition = modelCenter;

            eyePosition.Z += modelRadius * 2;
            eyePosition.Y += modelRadius;

            float aspectRatio = Game.GraphicsDevice.Viewport.AspectRatio;

            float nearClip = modelRadius / 100;
            float farClip = modelRadius * 100;

            Matrix world = Matrix.CreateRotationY(rotation);
            Matrix view = Matrix.CreateLookAt(eyePosition, modelCenter, Vector3.Up);
            Matrix projection = Matrix.CreatePerspectiveFieldOfView(1, aspectRatio,
                                                                nearClip, farClip);

            // Draw the model.
            foreach (ModelMesh mesh in starship.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = boneTransforms[mesh.ParentBone.Index] * world;
                    effect.View = view;
                    effect.Projection = projection;

                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.SpecularPower = 16;
                }

                mesh.Draw();
            }

        }


        /// <summary>
        /// Whenever a new model is selected, we examine it to see how big
        /// it is and where it is centered. This lets us automatically zoom
        /// the display, so we can correctly handle models of any scale.
        /// </summary>
        void MeasureModel()
        {
            // Look up the absolute bone transforms for this model.
            boneTransforms = new Matrix[starship.Bones.Count];

            starship.CopyAbsoluteBoneTransformsTo(boneTransforms);

            // Compute an (approximate) model center position by
            // averaging the center of each mesh bounding sphere.
            modelCenter = Vector3.Zero;

            foreach (ModelMesh mesh in starship.Meshes)
            {
                BoundingSphere meshBounds = mesh.BoundingSphere;
                Matrix transform = boneTransforms[mesh.ParentBone.Index];
                Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform);

                modelCenter += meshCenter;
            }

            modelCenter /= starship.Meshes.Count;

            // Now we know the center point, we can compute the model radius
            // by examining the radius of each mesh bounding sphere.
            modelRadius = 0;

            foreach (ModelMesh mesh in starship.Meshes)
            {
                BoundingSphere meshBounds = mesh.BoundingSphere;
                Matrix transform = boneTransforms[mesh.ParentBone.Index];
                Vector3 meshCenter = Vector3.Transform(meshBounds.Center, transform);

                float transformScale = transform.Forward.Length();

                float meshRadius = (meshCenter - modelCenter).Length() +
                                   (meshBounds.Radius * transformScale);

                modelRadius = Math.Max(modelRadius, meshRadius);
            }
        }





    }
}